/**
 * 全站http配置
 *
 * axios参数说明
 * isSerialize是否开启form表单提交
 * isToken是否需要token
 */
import Vue from 'vue'
import axios from 'axios'
import { serialize } from '@/util/util'
import { getToken, getSsoToken, cleanAllCash } from '@/util/auth' // setTokenConfig
// import { Message } from 'element-ui'
import website from '@/config/website'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
// import { getTokenConfigObj } from '@/util/auth'
// import { redirectLogin, resetTokenConfig } from '@/util/redirect'
import router from '@/router/router'
import { refreshToken } from './refreshToken'

const Axios = axios.create({
  timeout: 60 * 1000 * 30,
  validateStatus: function(status) {
    return status >= 200 && status <= 500
  },
  withCredentials: true
})

// NProgress 配置
NProgress.configure({
  showSpinner: false
})

/**
   * 封装请求
   * @params config 请求配置
   * @params 额外代理前缀
   */
const instance = function(config, type) {
  const { method, params, data } = config
  const obj = {
    ...config,
    url: type ? type + config.url : process.env.VUE_APP_BASE_API + config.url
  }

  if (method === 'post' && params) {
    const formData = new FormData()
    for (const key in params) {
      let val = params[key]
      if ([undefined, null].includes(val)) {
        continue
      }
      if (typeof val === 'string') {
        // 去除左右两边空格
        val = val.replace(/(^\s*)|(\s*$)/g, '')
      }
      formData.append(key, val)
    }
    obj.data = formData
    delete obj.params
  } else if (method === 'post' && data) {
    obj.data = data
  }
  if (obj.data instanceof Object) {
    for (const key in obj.data) {
      if (typeof obj.data[key] === 'string') {
        obj.data[key] = obj.data[key].replace(/(^\s*)|(\s*$)/g, '')
      }
    }
  }
  return Axios(obj)
}
// http request拦截
Axios.interceptors.request.use(config => {
  // 开启 progress bar
  NProgress.start()
  const meta = (config.meta || {})
  if (getSsoToken()) {
    try {
      config.headers['ssotoken'] = getSsoToken()
      config.headers['client'] = 'pc'
    } catch (error) {
      console.error(error)
    }
  }
  if (getToken()) {
    // try {
    //   const tokenConfigObj = getTokenConfigObj()
    //   config.headers[tokenConfigObj.tokenName] = tokenConfigObj.tokenPrefix + ' ' + getToken()
    // } catch (error) {
    //   console.error(error)
    // }
    try {
      config.headers['Token'] = getToken()
    } catch (error) {
      console.error(error)
    }
  }
  // headers中配置serialize为true开启序列化
  if (config.method === 'post' && meta.isSerialize === true) {
    config.data = serialize(config.data)
  }

  let url = config.url
  // get参数编码
  if (config.method === 'get' && config.params) {
    if (!url.includes('?')) {
      url += '?'
      const keys = Object.keys(config.params)
      let keyV = ''
      for (const key of keys) {
        keyV = config.params[key]
        if (config.params[key] === undefined || config.params[key] === null) {
          keyV = ''
        }
        url += `${key}=${encodeURIComponent(keyV)}&`
      }
      url = url.substring(0, url.length - 1)
      config.params = {}

      config.url = url
    }
  }

  return refreshToken(config)
}, error => {
  return Promise.reject(error)
})

/**
  * 是否是刷新请求返回结果
  * @param {*} res
  */
const isRefreshRespone = (res) => {
  if (!res || !res.config || !res.config.data) {
    return false
  }
  const data = res.config.data

  const isFormData = data instanceof FormData
  if (!isFormData) {
    return false
  }
  const grantType = data.get('grant_type')
  return grantType === 'refresh_token'
}

// http response 拦截
Axios.interceptors.response.use(res => {
  // 关闭 progress bar
  NProgress.done()
  // 获取状态码
  const status = res.data.status || res.status
  const statusWhiteList = website.statusWhiteList || []
  const message = res.data.msg || res.data.error_description || '未知错误'
  // 如果在白名单里则自行catch逻辑处理
  if (statusWhiteList.includes(status)) return Promise.reject(res)
  // 如果是401则跳转到登录页面
  if (status === 401) {
    // if (res.data.data && res.data.data.tokenData) {
    //   setTokenConfig(res.data.data)
    //   redirectLogin(res.data.data)
    // } else {
    //   resetTokenConfig()
    // }
    cleanAllCash()
    // const callBackUrl = window.location.protocol + '//' + window.location.host + '/back'
    // window.location.replace(process.env.VUE_APP_HOME_LOGIN + '?back=' + callBackUrl || '')
    router.replace('/login')
    return res
  }

  // 如果请求为非200否者默认统一处理
  if (status !== 200) {
    // 刷新token接口如果异常，前端忽略提示
    if (isRefreshRespone(res)) {
      console.error(res)
      return Promise.reject(res)
    }
    Vue.prototype.$message({
      message: message,
      type: 'error'
    })
    return Promise.reject(new Error(message))
  }
  return res
}, error => {
  Vue.prototype.$message({
    message: error.message,
    type: 'error'
  })
  NProgress.done()
  return Promise.reject(new Error(error))
})

/**
 * 文件下载
 * @param {*} url 下载文件地址
 * @param {*} params 下载文件需要的参数
 * @param {*} fileName 下载文件名 (如果为空则设置为后台返回的文件名 建议使用后台返回的文件名)
 * @param {*} requestType 请求方式
 */
export function exportFile(url, params, fileName = '', requestType = 'get') {
  return new Promise((resolve, reject) => {
    const thenFunc = res => {
      blob(res.data, fileName || getDownFileName(res))
      resolve()
    }

    const config = { headers: { 'Content-Type': 'application/vnd.ms-excel' }, responseType: 'blob' }

    if (requestType === 'get') {
      axios.get(url, { params, ...config }).then(thenFunc).catch((e) => {
        console.error(e)
        reject(e)
      })
    }

    if (requestType === 'post') {
      const formData = new FormData()
      for (const key in params) {
        if (params[key] !== null) {
          formData.append(key, params[key])
        }
      }
      axios.post(url, formData, config).then(thenFunc).catch((e) => {
        console.error(e)
        reject(e)
      })
    }
  })
}

// const BLOB_TYPE = {
//   default: '',
//   office: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8'
// }

/**
 * 通过blob下载文件
 * @param {*} data 文件数据
 * @param {*} fileName 保存的文件名
 * @param {*} type blob类型
 */
const blob = (data, fileName, blobType = '') => {
  const blob = new Blob([data], { type: blobType })
  const objectUrl = URL.createObjectURL(blob)
  const link = document.createElement('a')// 我们用模拟q标签点击事件
  link.href = objectUrl
  link.setAttribute('download', fileName)
  document.body.appendChild(link)
  link.click()// 点击
  document.body.removeChild(link) // 下载完成移除元素
  window.URL.revokeObjectURL(URL) // 释放掉blob对象
}

/**
 * 获取下载的文件名
 */
function getDownFileName(response) {
  const headers = response.headers
  const name = headers['content-disposition'] // 这里如果没有获取到，联系后端设置一下headers
  let filename = ''
  let t = /filename="([^;]*);?"/i.exec(name)
  t === null && (t = /filename=([^;]*);?/i.exec(name))
  if (t !== null && t.length > 1) {
    filename = decodeURIComponent(t[1]) // 以上几步是为了获取传递过来的文件名，
  }

  return filename
}

window.axios = Axios

export default instance
